#!/bin/sh
#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
set +x

#@dest:  to check oracle archive dest using
#@date:  2015-01-24
#@authr: 
USAGE="Usage: ./oraclecheckarchive.sh AgentRoot PID"

SCRIPT_ROOT_PATH=$1
PID=$2
PARAM_NUM=$3

. "${SCRIPT_ROOT_PATH}"/oracle_sbin_func.sh

PARAM_CONTENT=`read_input_param "${PARAM_NUM}"`
test -z "$PARAM_CONTENT"                                       && exit_with_error "PARAM_FILE"

DBINSTANCE=`get_value "${PARAM_CONTENT}" InstanceName`
DBARCHIVE_LIMEN=`get_value "${PARAM_CONTENT}" ArchiveThreshold`
DBUSER=`get_value "${PARAM_CONTENT}" UserName`
DBUSERPWD=`get_value "${PARAM_CONTENT}" Password`
ASMSIDNAME=`get_value "${PARAM_CONTENT}" ASMInstanceName`
ORACLE_BASE=`get_value "${PARAM_CONTENT}" AccessOracleBase`
ORACLE_HOME=`get_value "${PARAM_CONTENT}" AccessOracleHome`

if [ -z "${ASMSIDNAME}" ]; then
    ASMSIDNAME="+ASM"
fi

AUTHMODE=0
if [ "$DBUSERPWD" = "" ]; then
    AUTHMODE=1
fi

DBROLE=
if [ "${DBUSER}" = "sys" ]; then
    DBROLE="as sysdba"
fi

if [ "$DBARCHIVE_LIMEN" = "" ]; then
    DBARCHIVE_LIMEN=0
fi

log_info "DBINSTANCE=${DBINSTANCE};DBUSER=${DBUSER};DBARCHIVE_LIMEN=${DBARCHIVE_LIMEN};\
AUTHMODE=$AUTHMODE;IN_ORACLE_HOME=$IN_ORACLE_HOME"

# check oracle install type
check_oracle_install_type

#get oracle user info
get_oracle_user 

#get oracle user shell type
get_oracle_user_shell_type 

env_file_list=`get_user_env_file "${ORA_DB_USER}"`
if [ $? -ne 0 ] || [ -z "$env_file_list" ]; then
    log_error "Get user env file failed"
    exit "$RETURN_INVALID"
fi

EXPORT_ORACLE_ENV=`generate_export_cmd "$env_file_list" "oracle"`
if [ $? -ne 0 ] || [ -z "$EXPORT_ORACLE_ENV" ]; then
    log_error "Get user env cmd failed"
    exit "$RETURN_INVALID"
fi

if [ "$DBISCLUSTER" -gt 0 ]; then
    # get grid user
    get_grid_user
    get_grid_user_shell_type
    get_grid_home_path

    env_file_list=`get_user_env_file "${ORA_GRID_USER}"`
    if [ $? -ne 0 ] || [ -z "$env_file_list" ]; then
        log_error "Get user env file failed"
        exit "$RETURN_INVALID"
    fi

    EXPORT_GRID_ENV=`generate_export_cmd "$env_file_list" "grid"`
    if [ $? -ne 0 ] || [ -z "$EXPORT_GRID_ENV" ]; then
        log_error "Get user env cmd failed"
        exit "$RETURN_INVALID"
    fi

    ASMSIDNAME=`ps -ef | grep asm_...._+ | grep -v grep | ${MYAWK} -F_ '{print $NF}' | uniq`
    if [ -z "$ASMSIDNAME" ]; then
        log_error "Have no asm instance"
        exit "${RETURN_INVALID}"
    fi
fi

#get oracle base path
get_oracle_base_path

#get oracle home path
get_oracle_home_path

#get oracle version
get_oracle_version

# Archive Log
ARCHIVEDESTSQL="${STMP_PATH}/ArchiveDestSQL${PID}.sql"
ARCHIVEDESTRST="${TMP_PATH}/ArchiveDestRST${PID}.txt"
ARCHIVE_DEST_LIST="${TMP_PATH}/ArchiveDestList${PID}.txt"
#********************************define these for local script********************************

check_archive_mode_and_archive_using()
{
    # create check archive mode sql
    log_info "Begin check archive dest directory."
    echo "set linesize 300;" > "${ARCHIVEDESTSQL}"
    echo "col DESTINATION for a255;" >> "${ARCHIVEDESTSQL}"
    echo "select DESTINATION from v\$archive_dest where STATUS='VALID';" >> "${ARCHIVEDESTSQL}"
    echo "exit" >> "${ARCHIVEDESTSQL}"
    set_db_silence_sql "${ARCHIVEDESTSQL}"

    log_info "Exec SQL to get destination of archive dest(INACTIVE)."
    oracle_exe_sql "${DBUSER}" "${DBUSERPWD}" "${ARCHIVEDESTSQL}" "${ARCHIVEDESTRST}" "${DBINSTANCE}" 600 1
    RET_CODE=$?
    if [ "$RET_CODE" -ne "0" ]; then
        delete_file "${ARCHIVEDESTSQL}" "${ARCHIVEDESTRST}"
        log_error "Get Archive log dest list failed."
        exit ${RET_CODE}
    fi
        
    delete_file "${ARCHIVE_DEST_LIST}"
    cat "${ARCHIVEDESTRST}" | grep "^/" >> "${ARCHIVE_DEST_LIST}"
    cat "${ARCHIVEDESTRST}" | grep "^+" >> "${ARCHIVE_DEST_LIST}"
    cat "${ARCHIVEDESTRST}" | grep "USE_DB_RECOVERY_FILE_DEST" >> "${ARCHIVE_DEST_LIST}"
    delete_file "${ARCHIVEDESTSQL}" "${ARCHIVEDESTRST}"
    
    exec 4<&0
    exec <"${ARCHIVE_DEST_LIST}"
    while read line; do
        STRARCHIVEDEST=$line
        if [ -z "${STRARCHIVEDEST}" ]; then
            continue
        fi
        IS_RECOVERY_FILE_DEST=0
        FAST_USEDCAPACITY=0
        FAST_ALLCAPACITY=0
        
        log_info "STRARCHIVEDEST=${STRARCHIVEDEST}"
        # default dest, need to search direcory
        if [ "${STRARCHIVEDEST}" = "USE_DB_RECOVERY_FILE_DEST" ]; then
            IS_RECOVERY_FILE_DEST=1
            # get archive dest
            echo "set linesize 300;" > "${ARCHIVEDESTSQL}"
            echo "col NAME for a255;" >> "${ARCHIVEDESTSQL}"
            echo "select NAME from V\$RECOVERY_FILE_DEST;" >> "${ARCHIVEDESTSQL}"
            echo "exit" >> "${ARCHIVEDESTSQL}"

            log_info "Exec SQL to get name of archive dest."
            oracle_exe_sql "${DBUSER}" "${DBUSERPWD}" "${ARCHIVEDESTSQL}" "${ARCHIVEDESTRST}" "${DBINSTANCE}" 600 1
            RET_CODE=$?
            if [ "$RET_CODE" -ne "0" ]; then
                delete_file "${ARCHIVEDESTSQL}" "${ARCHIVEDESTRST}"
                delete_file "${ARCHIVE_DEST_LIST}" 
                log_info "Get Archive dest failed."
                exit ${RET_CODE}
            fi
    
            STRARCHIVEDEST=`cat "${ARCHIVEDESTRST}" | ${MYAWK} '{print $1}'`
            log_info "STRARCHIVEDEST=${STRARCHIVEDEST}."
            delete_file "${ARCHIVEDESTSQL}" "${ARCHIVEDESTRST}"
            
            # get archive using
            echo "set linesize 100;" > "${ARCHIVEDESTSQL}"
            echo "select SPACE_LIMIT/1024/1024,SPACE_USED/1024/1024 from V\$RECOVERY_FILE_DEST; " >> "${ARCHIVEDESTSQL}"
            echo "exit" >> "${ARCHIVEDESTSQL}"

            log_info "Exec SQL to get using of archive dest."
            oracle_exe_sql "${DBUSER}" "${DBUSERPWD}" "${ARCHIVEDESTSQL}" "${ARCHIVEDESTRST}" "${DBINSTANCE}" 600 1
            RET_CODE=$?
            if [ "$RET_CODE" -ne "0" ]; then
                delete_file "${ARCHIVEDESTSQL}" "${ARCHIVEDESTRST}"
                delete_file "${ARCHIVE_DEST_LIST}" 
                log_info "Get Archive dest using failed."
                exit ${RET_CODE}
            fi
            
            #get result like below, and get the content between ----- and black
            #   Connected to:
            #   Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
            #   With the Partitioning, OLAP, Data Mining and Real Application Testing options
            #
            #
            #   STATUS
            #   ------------
            #   OPEN
            #
            #   Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
            TMPLINE=`cat "${ARCHIVEDESTRST}" | ${MYAWK} '{print $1";"$2}'`
            for i in ${TMPLINE}; do
                FAST_ALLCAPACITY=`echo "$i" | ${MYAWK} -F ";" '{print $1}'`
                FAST_USEDCAPACITY=`echo "$i" | ${MYAWK} -F ";" '{print $2}'`
                # deal number pot
                FAST_ALLCAPACITY=`echo "$FAST_ALLCAPACITY" | ${MYAWK} -F "." '{print $1}'`
                FAST_USEDCAPACITY=`echo "$FAST_USEDCAPACITY" | ${MYAWK} -F "." '{print $1}'`
                # first value
                break
            done
            
            delete_file "${ARCHIVEDESTSQL}" "${ARCHIVEDESTRST}"
            lof_info "FAST_ALLCAPACITY=$FAST_ALLCAPACITY;FAST_USEDCAPACITY=$FAST_USEDCAPACITY"
        else
            # check whether the archive dest is exists, if not, the suffix maybe is the perfix of the archive files.
            #.eg 
            # Archive destination            /lvoracle/app/oracle/11.2.0/db_1/dbs/arch/abc
            # the last abc mabe is the perfix of the archive files.
            LASTCHAR=`echo "${STRARCHIVEDEST}" | ${MYAWK} '{print substr($NF,length($NF),1)}'`
            if [ "`rd_substr "$STRARCHIVEDEST" 1 1`" = "/" ] && [ "${LASTCHAR}" != "/" ] && [ ! -d "${STRARCHIVEDEST}" ]; then
                FILEPREFIX=`echo "${STRARCHIVEDEST}" | ${MYAWK} -F "/" '{print $NF}'`
                LENPREFIX=`echo "$FILEPREFIX" | ${MYAWK} '{print length($1)}'`
                LENALLDEST=`echo "$STRARCHIVEDEST" | ${MYAWK} '{print length($1)}'`
                
                LENDEST=`expr "$LENALLDEST" - "$LENPREFIX" - 1`
                STRARCHIVEDEST=`rd_substr "$STRARCHIVEDEST" 1 "$LENDEST"`
            fi
            
            if [ ! -d "${STRARCHIVEDEST}" ]; then
                log_info "Archive Dest ${STRARCHIVEDEST} is not exists"
            fi
        fi
        
        log_info "STRARCHIVEDEST=${STRARCHIVEDEST}"
        if [ "`rd_substr "$STRARCHIVEDEST" 1 12`" = "/dev/raw/raw" ]; then
            log_info "Archive dest ${STRARCHIVEDEST} is the raw, not support check archive dest size."
            continue
        fi
        
        FREECAPACITY=0
        ALLCAPACITY=0
        #file system
        if [ "`rd_substr "$STRARCHIVEDEST" 1 1`" = "/" ]; then
            if [ "${SYS_NAME}" = "HP-UX" ]; then
                FREECAPACITY=`df -k "$STRARCHIVEDEST" | sed '1d' | $MYAWK '{print $1}' | sed -n '1p'`
                FREECAPACITY=`expr "$FREECAPACITY" / 1024`
                ALLCAPACITY=`df -k "$STRARCHIVEDEST" | sed '2,4d' | $MYAWK -F ":" '{print $2}' | $MYAWK '{print $1}'`
                ALLCAPACITY=`expr "$ALLCAPACITY" / 1024`
            elif [ "${SYS_NAME}" = "AIX" ]; then
                FREECAPACITY=`df -k "$STRARCHIVEDEST" | sed '1d' | $MYAWK '{print $3}'`
                FREECAPACITY=`expr "$FREECAPACITY" / 1024`
                ALLCAPACITY=`df -k "$STRARCHIVEDEST" | sed '1d' | $MYAWK '{print $2}'`
                ALLCAPACITY=`expr "$ALLCAPACITY" / 1024`
            elif [ "${SYS_NAME}" = "SunOS" ]; then
                FREECAPACITY=`df -k "$STRARCHIVEDEST" | sed '1d' | $MYAWK '{print $4}'`
                FREECAPACITY=`expr "$FREECAPACITY" / 1024`
                ALLCAPACITY=`df -k "$STRARCHIVEDEST" | sed '1d' | $MYAWK '{print $2}'`
                ALLCAPACITY=`expr "$ALLCAPACITY" / 1024`
            else
                LINENUM=`df -m "$STRARCHIVEDEST" | wc -l | $MYAWK '{print $1}'`
                if [ "$LINENUM" = "2" ]; then
                    FREECAPACITY=`df -m "$STRARCHIVEDEST" | sed '1d' | $MYAWK '{print $4}'`
                    ALLCAPACITY=`df -m "$STRARCHIVEDEST" | sed '1d' | $MYAWK '{print $2}'`
                else
                    FREECAPACITY=`df -m "$STRARCHIVEDEST" | sed '1,2d' | $MYAWK '{print $3}'`
                    ALLCAPACITY=`df -m "$STRARCHIVEDEST" | sed '1,2d' | $MYAWK '{print $1}'`
                fi
            fi
            log_info "file system capacity:ALLCAPACITY=$ALLCAPACITY,FREECAPACITY=$FREECAPACITY."
        fi

        #archive dest
        if [ "`rd_substr "$STRARCHIVEDEST" 1 1`" = "+" ]; then
            ASMSIDNAME=`ps -ef | grep "asm_...._${ASMSIDNAME}" | grep -v "grep" | ${MYAWK} -F '+' '{print $NF}' | uniq`
            ASMSIDNAME=`echo "${ASMSIDNAME}" | ${MYAWK} -F " " '{print $1}'`
            ASMSIDNAME="+"${ASMSIDNAME}
            log_info "Check ASM instance name $ASMSIDNAME."

            #check ASM instance status
            ASMINSTNUM=`ps -ef | grep "asm_...._${ASMSIDNAME}" | grep -v "grep" | wc -l | $MYAWK '{print $1}'`
            if [ "${ASMINSTNUM}" -eq "0" ]; then
                log_info "The ASM instance is not open."
                DeleteFile "${ARCHIVE_DEST_LIST}"
                exit "${ERROR_ORACLE_ASM_INSTANCE_NOSTART}"
            fi

            ASM_DEST=`rd_substr "$STRARCHIVEDEST" 2`
            ASM_DISKGROUPNAME=`echo "$ASM_DEST" | $MYAWK -F "/" '{print $1}'`
            
            GetASMUsage
            log_info "ASM capacity:ALLCAPACITY=$ALLCAPACITY,FREECAPACITY=$FREECAPACITY."
        fi

        used=`expr "${ALLCAPACITY}" - "${FREECAPACITY}"`
        usedRate=`${MYAWK} 'BEGIN{printf "%.0f\n",('"$used"'/'"$ALLCAPACITY"')*100}'`
        if [ "${FAST_ALLCAPACITY}" -gt 0 ]  && [ "${FAST_USEDCAPACITY}" -gt 0 ]; then
            usedRate_Fast=`${MYAWK} 'BEGIN{printf "%.0f\n",('"$FAST_USEDCAPACITY"'/'"$FAST_ALLCAPACITY"')*100}'`
            if [ "${usedRate_Fast}" -gt "${usedRate}" ]; then
                usedRate=${usedRate_Fast}
            fi
        fi
        if [ "${usedRate}" -ge "${DBARCHIVE_LIMEN}" ]; then
            log_info "archive dest(${STRARCHIVEDEST}) usedRate(${usedRate}%) is large than threshold."
            delete_file "${ARCHIVE_DEST_LIST}"
            exit "${ERROR_ORACLE_OVER_ARCHIVE_USING}"
        fi
    done
    exec 0<&4 4<&-
    
    delete_file "${ARCHIVE_DEST_LIST}"
    delete_file "${ARCHIVEDESTSQL}" "${ARCHIVEDESTRST}"
    log_info "success check archive dest directory using."
    return 0
}

GetASMUsage()
{
    if [ "$ORA_PREVERSION" -ge "11" ]; then
        ASMUser=${ORA_GRID_USER}
        SHELLTYPE=${GRID_SHELL_MODE}
    else
        ASMUser=${ORA_DB_USER}
        SHELLTYPE=${ORACLE_SHELL_MODE}
    fi
    SHELLTYPE=`cat /etc/passwd | grep "^${ASMUser}:" | ${MYAWK} -F "/" '{print $NF}'`
    if [ "$SHELLTYPE" = "csh" ]; then
        CMD_SETENV="setenv ORACLE_SID ${ASMSIDNAME};"
    else
        CMD_SETENV="ORACLE_SID=${ASMSIDNAME};export ORACLE_SID;"
    fi

    TMP_FILE="${STMP_PATH}/oracle_get_dg_cap_info_tmp_${PID}.txt"
    su - "${ASMUser}" "${SHELLTYPE}" -c "echo \"${ORACLE_MARK}\"; ${EXPORT_GRID_ENV} ${CMD_SETENV} echo lsdg ${ASM_DISKGROUPNAME} | asmcmd" > "${TMP_FILE}" 2>&1
    delete_oracle_mark "${TMP_FILE}"
    DGCapInfo=`cat "${TMP_FILE}" | grep "${ASM_DISKGROUPNAME}"`
    delete_file "${TMP_FILE}"

    TMP_FILE="${STMP_PATH}/oracle_get_dg_info_header_tmp_${PID}.txt"
    su - "${ASMUser}" "${SHELLTYPE}" -c "echo \"${ORACLE_MARK}\"; ${EXPORT_GRID_ENV} ${CMD_SETENV}; echo lsdg | asmcmd" > "${TMP_FILE}" 2>&1
    delete_oracle_mark "${TMP_FILE}"
    DGInfoHeader=`cat "${TMP_FILE}" | sed -n '1p' | ${MYAWK} '{$1="";print $0}'`
    delete_file "${TMP_FILE}"

    index=0
    TotalNum=0
    FreeNum=0
    for str in ${DGInfoHeader}; do
        let index+=1
        if [ "$str" == "Total_MB" ]; then
            TotalNum=${index}
        fi
        if [ "$str" == "Free_MB" ]; then
            FreeNum=${index}
        fi
    done
    index=0
    for str in ${DGCapInfo}; do
        let index+=1
        if [ ${index} -eq ${TotalNum} ]; then
            ALLCAPACITY=${str}
        fi
        if [ ${index} -eq ${FreeNum} ]; then
            FREECAPACITY=${str}
        fi
    done
}
#********************************check host enviroment begin********************************



check_db_invalid()
{
    ps -aef | sed 's/ *$//g' | grep "ora_...._${DBINSTANCE}$" | grep -v "grep" > /dev/null
    if [ "$?" = "0" ]; then
        base_info=`get_database_base_info "${DBINSTANCE}" "${DBUSER}" "${DBUSERPWD}"`
        if [ $? -ne 0 ] || [ -z "$base_info" ]; then
            log_error "Get database base info failed"
            exit $?
        fi
        log_mode=`echo "${base_info}" | $MYAWK '{print $1}'`
        if [ "${log_mode}" != "ARCHIVELOG" ]; then
            log_error "Archive Mode=No Archive Mode, check archive mode failed."
            exit "${ERROR_ORACLE_NOARCHIVE_MODE}"
        fi
        return 0  
    fi
    return 1
}
check_db_invalid
if [ "$?" -ne "0" ]; then
    exit 0
fi

#check archive mode & archive using
if [ "${DBARCHIVE_LIMEN}" -ne "0" ]; then
    check_archive_mode_and_archive_using
    if [ "$?" -ne "0" ]; then
        log_error "Exec checkArchiveModeAndArchiveUsing exec failed."
        exit "$ERROR_SCRIPT_EXEC_FAILED"
    fi
else
    log_info "DBARCHIVE_LIMEN is zero, not to check archive using."
fi

exit 0
